using System.Collections.Generic;

namespace RealDolmen.Helpers
{
    public class UrlPath
    {
        #region Properties
        private string queryString;

        public string QueryString
        {
            get { return queryString; }
            set { queryString = value; }
        }
        private string extension;

        public string Extension
        {
            get { return extension; }
            set { extension = value; }
        }
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private string server;

        public string Server
        {
            get { return server; }
            set { server = value; }
        }
        private string protocol;

        public string Protocol
        {
            get { return protocol; }
            set { protocol = value; }
        }
        private string directory;

        public string Directory
        {
            get { return directory; }
            set { directory = value; }
        }

        public string FullPath
        {
            get
            {
                return ComposePath(
                          Protocol,
                          Server,
                          Directory,
                          Name,
                          Extension,
                          QueryString);
            }
            set
            {
                QueryString = ExtractQueryString(value);
                string temp = ExtractUrlBeforeQueryString(value);
                Protocol = ExtractProtocol(temp);
                Server = ExtractServer(temp);
                Directory = ExtractDirectory(temp);
                Name = ExtractName(temp);
                Extension = ExtractExtension(temp);
            }
        }
        public string FullPathWithoutQueryString
        {
            get
            {
                return ComposePath(
                          Protocol,
                          Server,
                          Directory,
                          Name,
                          Extension,
                          string.Empty);
            }
        }
        #endregion // Properties

        #region Constructor
        public UrlPath(string fullpath)
        {
            FullPath = fullpath;
        } 
        #endregion // Constructor

        #region Static Methods
        public static bool IsPathSubsumed(string pathSubsumed, string pathSubsumer)
        {
            string pathSubsumerNormalized = pathSubsumer.ToLowerInvariant();
            string pathSubsumedNormalized = pathSubsumed.ToLowerInvariant();

            return pathSubsumedNormalized.StartsWith(pathSubsumerNormalized);
        }
        
        public static string ExtractExtension(string path)
        {
            int idx = path.LastIndexOf('.');

            if (idx < 0)
                return string.Empty;
            else
                return path.Substring(idx + 1);
        }
        public static string ExtractName(string path)
        {
            int idxDot = path.LastIndexOf('.');

            if (idxDot > -1)
                path = path.Substring(0, idxDot);

            int idxSlash = path.LastIndexOf('/');

            if (idxSlash < -1)
                return path;
            else
                return path.Substring(idxSlash + 1);
        }

        public static string ExtractProtocol(string path)
        {
            int idxDelimiter = path.IndexOf("://");
            if (idxDelimiter < 0)
                return string.Empty;

            return path.Substring(0, idxDelimiter);
        }

        public static string ExtractServer(string fullpath)
        {
            bool hasProtocol;
            string path = ExtractPath(fullpath, out hasProtocol);

            if (!hasProtocol)
                return string.Empty;
            else
            {
                int firstSlash = path.IndexOf('/');

                if (firstSlash < 0)
                    return string.Empty;
                else
                    return path.Substring(0, firstSlash);
            }
        }

        public static string ExtractDirectory(string fullpath)
        {
            bool hasProtocol;
            string path = ExtractPath(fullpath, out hasProtocol);

            if (!hasProtocol)
                return path;
            else
            {
                int firstSlash = path.IndexOf('/');

                if (firstSlash < 0)
                    return string.Empty;
                else
                    return path.Substring(firstSlash + 1);
            }
        }

        protected static string ExtractPath(string path, out bool hasProtocol)
        {
            int idxDelimiter = path.IndexOf("://");

            if (idxDelimiter < 0)
            {
                idxDelimiter = 0;
                hasProtocol = false;
            }
            else
            {
                idxDelimiter += 3;
                hasProtocol = true;
            }

            path = path.Substring(idxDelimiter);

            int idxSlash = path.LastIndexOf('/');

            if (idxSlash < 0)
                return string.Empty;
            else
                return path.Substring(0, idxSlash);
        }

        public static Dictionary<string, string> GetParametersFromQueryString(string queryString)
        {
            Dictionary<string, string> parametersResult = new Dictionary<string, string>();

            if (!string.IsNullOrEmpty(queryString))
            {
                string[] parameters = queryString.Split('&');

                foreach (string parameter in parameters)
                {
                    int idx = parameter.IndexOf('=');
                    if (idx > 0)
                    {
                        string key = parameter.Remove(idx).Trim();
                        string value = parameter.Substring(idx + 1).Trim();
                        parametersResult.Add(key, value);
                    }
                }
            }

            return parametersResult;
        }

        public static string ExtractQueryString(string url)
        {
            string queryString = string.Empty;
            int idx = url.IndexOf('?');
            if (idx > 0)
            {
                queryString = url.Substring(idx + 1);
            }
            return queryString;
        }
        public static string ExtractUrlBeforeQueryString(string url)
        {
            string extracted = url;
            int idx = extracted.IndexOf('?');
            if (idx > 0)
            {
                extracted = url.Remove(idx);
            }
            return extracted;
        }
        #endregion // Static Methods

        #region Helpers
        private string ComposePath(string protocol, string server, string directory, string name, string extension, string queryString)
        {
            string path = name;

            if (!string.IsNullOrEmpty(extension))
                path = string.Format("{0}.{1}", path, extension);

            if (!string.IsNullOrEmpty(directory))
                path = string.Format("{0}/{1}", directory, path);

            if (!string.IsNullOrEmpty(protocol))
                path = string.Format("{0}://{1}/{2}",
                            protocol,
                            server,
                            path);

            if (!string.IsNullOrEmpty(queryString))
                path = string.Format("{0}?{1}", path, queryString);

            return path;
        } 
        #endregion // Helpers
    }
}
